﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;
using System.IO;
using BattleCity.Rendering;
using BattleCity.GameLogic.Xml;

namespace BattleCity
{
    public class SingleLevelMenu
    {
        public enum Selection
        {
            Continue,
            NewGame,
            Start,
            None
        }

        Vector2[] stringsPositions;
        Vector2 menuWrapperPosition;
        Vector2 leftArrowPosition;
        Vector2 rightArrowPosition;

        Vector2 lockPosition;

        SpriteFont menuFont;
        Texture2D menuWrapper;
        Texture2D leftArrow;
        Texture2D rightArrow;
        Texture2D materialsTex;
        Texture2D levelTex;
        Texture2D tapped;
        Texture2D lockTex;
        SpriteBatch spriteBatch;
        Texture2D button;

        ContentManager content;

        BasicEffect effect;
        GraphicsDevice graphicsDevice;

        GridRenderer gridModel;
        BlocksRenderer blocksModel;

        public int selectedLevel;

        public bool levelChooser;
        public bool continueAvailable;
        public bool newLevelView;
        bool lockedLevel = false;

        Vector2 screenCenter;

        float tappedCounter = 0.0f;
        Selection selected = Selection.None;
        int buttonX;

        public SingleLevelMenu(bool continueAvailable, Vector2 screenCenter, SpriteFont menuFont, Texture2D menuWrapper, SpriteBatch spriteBatch, ContentManager content, GraphicsDevice graphicsDevice)
        {
            this.continueAvailable = continueAvailable;
            this.menuWrapper = menuWrapper;
            this.menuFont = menuFont;
            this.spriteBatch = spriteBatch;
            this.content = content;
            this.graphicsDevice = graphicsDevice;
            this.screenCenter = screenCenter;

            selectedLevel = 1;
          
            stringsPositions = new Vector2[6];
          
            stringsPositions[0] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.CONTINUE).X * 0.5f, 50.0f);
            stringsPositions[1] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.NEWGAME).X * 0.5f, 160.0f);
            stringsPositions[3] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.LEVEL + " " + selectedLevel.ToString()).X * 0.5f, 50.0f);
            #if WINDOWS_PHONE 
            stringsPositions[2] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.STARTGAME).X * 0.5f, 380.0f);
            menuWrapperPosition = new Vector2(screenCenter.X - 200, 0.0f);
            #else
            stringsPositions[2] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.STARTGAME).X * 0.5f, 660.0f);
            menuWrapperPosition = new Vector2(screenCenter.X - 300, 0.0f);
            #endif

            stringsPositions[4] = new Vector2(screenCenter.X - menuFont.MeasureString("Not available in").X * 0.5f, 370.0f);
            stringsPositions[5] = new Vector2(screenCenter.X - menuFont.MeasureString("Trial mode").X * 0.5f, 410.0f);

            leftArrow = content.Load<Texture2D>(@"menu\left_arrow");
            rightArrow = content.Load<Texture2D>(@"menu\right_arrow");
            materialsTex = content.Load<Texture2D>(@"block_textures\material_tex_mip");

        
            leftArrowPosition = new Vector2(20, screenCenter.Y - (leftArrow.Height * 0.5f));
            rightArrowPosition = new Vector2((screenCenter.X * 2) - leftArrow.Width - 20, screenCenter.Y - (leftArrow.Height * 0.5f));
            button = content.Load<Texture2D>(@"menu\button");
            tapped = content.Load<Texture2D>(@"menu\tapped_button");
            lockTex = content.Load<Texture2D>(@"menu\lock");
            buttonX = (int)screenCenter.X - (button.Width / 2);


            lockPosition = new Vector2(screenCenter.X - lockTex.Width * 0.5f, screenCenter.Y - lockTex.Height * 0.65f);
            effect = new BasicEffect(graphicsDevice);
            effect.View = Matrix.CreateLookAt(new Vector3(0, 28, 45), new Vector3(0, 0, 0), -Vector3.UnitZ);
            effect.Projection = Matrix.CreatePerspectiveFieldOfView(0.95f, graphicsDevice.Viewport.AspectRatio, 1, 1000);

            //setto tecnica e materiali per il rendering della griglia e dei blocchi
            effect.World = Matrix.Identity;
            effect.LightingEnabled = true;
            effect.TextureEnabled = true;
            effect.Texture = materialsTex;

            if (!continueAvailable)
            {
                levelChooser = true;
                newLevelView = true;
                loadLevelScreen(selectedLevel);
            }
            else
            {
                newLevelView = false;
                levelChooser = false;
            }
            

        }

        public void Update(Vector2 gsPosition)
        {
            if (levelChooser)
            {
                if(gsPosition.X >= menuWrapperPosition.X + menuWrapper.Width)
                {
                    selectedLevel++;

                    #if WINDOWS_PHONE
                    if (Guide.IsTrialMode)
                    {
                        if (selectedLevel > 3) lockedLevel = true;
                        else lockedLevel = false;
                    }
                    #endif
                   
                    if (selectedLevel == 16) selectedLevel = 1;
                    
                    loadLevelScreen(selectedLevel);
                    newLevelView = true;
                    if (Options.soundEnabled) Sound.playSound(ref Sound.buttonPressed);
                    stringsPositions[3] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.LEVEL + " " + selectedLevel.ToString()).X * 0.5f, 50.0f);
                }

                if (gsPosition.X <= menuWrapperPosition.X)
                {
                    selectedLevel--;
                    if (selectedLevel == 0) selectedLevel = 15;
           
                    #if WINDOWS_PHONE
                    if ((selectedLevel > 3) && Guide.IsTrialMode) lockedLevel = true;
                    else lockedLevel = false;
                    #endif

                    loadLevelScreen(selectedLevel);
                    newLevelView = true;
                    if (Options.soundEnabled) Sound.playSound(ref Sound.buttonPressed);
                    stringsPositions[3] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.LEVEL + " " + selectedLevel.ToString()).X * 0.5f, 50.0f);
                }

                if ((gsPosition.X >= menuWrapperPosition.X) && (gsPosition.X <= menuWrapperPosition.X + menuWrapper.Width))
                {
                    
                    if ((gsPosition.Y > stringsPositions[2].Y) && (!lockedLevel)) selected = Selection.Start;
                }
            }
            else
            {
                if ((gsPosition.X >= menuWrapperPosition.X) && (gsPosition.X <= menuWrapperPosition.X + menuWrapper.Width))
                {
                    if (gsPosition.Y < stringsPositions[0].Y + menuFont.MeasureString(strings.CONTINUE).Y)
                        selected = Selection.Continue;
                    else if (gsPosition.Y < stringsPositions[1].Y + menuFont.MeasureString(strings.NEWGAME).Y)
                    {
                        selected = Selection.NewGame;                  
                    }     
                }
            }

            if (selected != Selection.None)
            {
                if (Options.soundEnabled) Sound.playSound(ref Sound.buttonPressed);
                tappedCounter = 0.2f;
            }
        }

        public void UpdateCounter(MenuManager manager, float dt)
        {
            if (tappedCounter > 0.0f)
            {
                tappedCounter -= dt;

            }

            if ((tappedCounter <= 0.0f) && (selected != Selection.None))
            {
                tappedCounter = 0.0f;
                switch (selected)
                {
                    case Selection.Continue:
                        manager.singleLevelContinue();
                        break;
                    case Selection.NewGame:
                        levelChooser = true;
                        loadLevelScreen(selectedLevel);
                        newLevelView = true;
                        stringsPositions[3] = new Vector2(screenCenter.X - menuFont.MeasureString(strings.LEVEL + " " + selectedLevel.ToString()).X * 0.5f, 50.0f);
                        break;
                    case Selection.Start:
                        manager.singleLevelStart(selectedLevel);
                        break;
                }
                selected = Selection.None;
            }
        }

        public void Draw()
        {
            
            spriteBatch.Draw(menuWrapper, menuWrapperPosition, Color.White);
            if (levelChooser)
            {
                spriteBatch.Draw(leftArrow, leftArrowPosition, Color.White);
                spriteBatch.Draw(rightArrow, rightArrowPosition, Color.White);

                if (!lockedLevel)
                {
                    spriteBatch.Draw(getButton(Selection.Start), new Vector2(buttonX, stringsPositions[2].Y - 20), Color.White);
                    spriteBatch.DrawString(menuFont, strings.STARTGAME, stringsPositions[2] + new Vector2(2, 2), Color.Black);
                    spriteBatch.DrawString(menuFont, strings.STARTGAME, stringsPositions[2], Color.DarkCyan);
                }
                else
                {
                    spriteBatch.DrawString(menuFont, "Not available in", stringsPositions[4], Color.Green);
                    spriteBatch.DrawString(menuFont, "Trial mode", stringsPositions[5], Color.Green);
                }

                spriteBatch.DrawString(menuFont, strings.LEVEL + " " + selectedLevel.ToString(), stringsPositions[3], Color.Green);

                spriteBatch.Draw(levelTex, new Vector2(screenCenter.X - levelTex.Width * 0.5f, 50), Color.White);

            }
            else
            {
                spriteBatch.Draw(getButton(Selection.Continue), new Vector2(buttonX, stringsPositions[0].Y - 20), Color.White);
                spriteBatch.Draw(getButton(Selection.NewGame), new Vector2(buttonX, stringsPositions[1].Y - 20), Color.White);

                spriteBatch.DrawString(menuFont, strings.CONTINUE, stringsPositions[0] + new Vector2(2, 2), Color.Black);
                spriteBatch.DrawString(menuFont, strings.NEWGAME, stringsPositions[1] + new Vector2(2, 2), Color.Black);

                spriteBatch.DrawString(menuFont, strings.CONTINUE, stringsPositions[0], Color.DarkCyan);
                spriteBatch.DrawString(menuFont, strings.NEWGAME, stringsPositions[1], Color.DarkCyan);
            }
        }

        public void loadLevelScreen(int level)
        {
                String path = @"Levels\level_" + level.ToString() + ".xml";
                Stream levelFileStream = TitleContainer.OpenStream(path);
                XmlSerializer deserializer = new XmlSerializer(typeof(SerializableTuple<BlockType, bool[]>[]));
                SerializableTuple<BlockType, bool[]>[] levelMap = (SerializableTuple<BlockType, bool[]>[])deserializer.Deserialize(levelFileStream);

                BattleCity.GameLogic.Xml.SerializableGameState.loadLevel(levelMap, false);
                levelFileStream.Close();

                gridModel = new GridRenderer(graphicsDevice);
                blocksModel = new BlocksRenderer(graphicsDevice);
        }

        public void DrawLevel()
        {
            newLevelView = false;

            spriteBatch.End();

            RenderTarget2D rt = new RenderTarget2D(graphicsDevice, 400, 300, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);
            Color[] levelColorData = new Color[400 * 300];
            graphicsDevice.SetRenderTarget(rt);
            graphicsDevice.Clear(new Color(0, 0, 0, 0));

            effect.CurrentTechnique.Passes[0].Apply();
            graphicsDevice.DepthStencilState = DepthStencilState.Default;

            //Grid Rendering
            graphicsDevice.Indices = gridModel.IndexBuffer;
            graphicsDevice.SetVertexBuffer(gridModel.VertexBuffer);
            graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, gridModel.VertexBuffer.VertexCount, 0, gridModel.PrimitiveCount);


            //Block Rendering
            graphicsDevice.Indices = blocksModel.indexBuffers[0];
            graphicsDevice.SetVertexBuffer(blocksModel.vertexBuffers[0]);
            graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, blocksModel.vertexBuffers[0].VertexCount, 0, blocksModel.PrimitiveCount(0));

            graphicsDevice.Indices = blocksModel.indexBuffers[1];
            graphicsDevice.SetVertexBuffer(blocksModel.vertexBuffers[1]);
            graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, blocksModel.vertexBuffers[1].VertexCount, 0, blocksModel.PrimitiveCount(1));

            graphicsDevice.SetRenderTarget(null);

            rt.GetData<Color>(levelColorData);
            levelTex = new Texture2D(graphicsDevice, 400, 300);
            levelTex.SetData<Color>(levelColorData);

            spriteBatch.Begin();

           
        }

        Texture2D getButton(Selection buttonPressed)
        {
            if (selected == buttonPressed) return tapped;
            else return button;
        }
    }
}